package com.iocaop.uaa.validation;


import com.iocaop.uaa.annotation.ValidPassword;
import lombok.RequiredArgsConstructor;
import org.passay.CharacterRule;
import org.passay.EnglishCharacterData;
import org.passay.EnglishSequenceData;
import org.passay.IllegalSequenceRule;
import org.passay.LengthRule;
import org.passay.PasswordData;
import org.passay.PasswordValidator;
import org.passay.RuleResult;
import org.passay.WhitespaceRule;
import org.passay.spring.SpringMessageResolver;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;

@RequiredArgsConstructor
public class PasswordConstraintValidator implements ConstraintValidator<ValidPassword, String> {
    // 引入passay中的消息解析器
    private final SpringMessageResolver springMessageResolver;
    @Override public void initialize(ValidPassword constraintAnnotation) {
    }

    @Override public boolean isValid(String password, ConstraintValidatorContext constraintValidatorContext) {
        // passay框架密码校验规则创建  参数1 消息解析器，参数2 校验规则
        PasswordValidator passwordValidator = new PasswordValidator(springMessageResolver,Arrays.asList(
            // 长度规则 8-30
            new LengthRule(8,30),
            // 至少1个大写字母
            new CharacterRule(EnglishCharacterData.UpperCase,1),
            // 至少1个小写字母
            new CharacterRule(EnglishCharacterData.LowerCase,1),
            // 至少1个小写字符
            new CharacterRule(EnglishCharacterData.Special,1),
            // 不允许有5个连续的字符
            new IllegalSequenceRule(EnglishSequenceData.Alphabetical,5,false),
            // 不允许5个连续数字
            new IllegalSequenceRule(EnglishSequenceData.Numerical,5,false),
            // 不允许有键盘上连续5个如：QWERTY
            new IllegalSequenceRule(EnglishSequenceData.USQwerty,5,false),
            // 不允许空格
            new WhitespaceRule()
        ));
        // 校验
        RuleResult result = passwordValidator.validate(new PasswordData(password));

        // 将原来的校验失败的机制停用
        constraintValidatorContext.disableDefaultConstraintViolation();
        // 设置成自定义的校验失败提示机制
        constraintValidatorContext.buildConstraintViolationWithTemplate(String.join(",",passwordValidator.getMessages(result)))
            .addConstraintViolation();
        return result.isValid();
    }
}
